﻿#include <iostream>
#include <graphics.h>
#include <conio.h>
#include <time.h>
using namespace std;

#define MAXSIZE 100
#define R 5
typedef struct Snake {//蛇结构体
	int speed = 0;//速度
	pair<int, int> coor[MAXSIZE] = {};
	int dir = 2;
	int length = 3;
};

typedef struct food {//食物结构体
	pair<int, int> place[MAXSIZE] = {};
	int score;
};

void Initfood(food& F)
{//初始化食物
	F.score = 0;
	srand(time(NULL));
	for (int i = 0; i < 100; i++)
	{
		F.place[i].first = rand() % (640 - R) + R;
		F.place[i].second = rand() % (480 - R) + R;
	}
}

void hatch(Snake& S)
{//初始化蛇
	S.length = 3;
	S.dir = 2;
	S.speed = 0;
	for (int i = 0; i < 3; i++)
	{
		S.coor[i].first = 40 - i * 10;
		S.coor[i].second = 30;
	}
}

void control_speed(int& speed)
{//调整蛇的速度
	cleardevice();
	outtextxy(280, 180, "请选择蛇的速度1-5");
	char ch = _getch();
	speed = ch - '0';
}

void control_dir(int& DIR)
{//控制蛇头的方向
	char ch = _getch();
	switch (ch)
	{
	case 72:
	case 'W':
	case 'w':
		if (DIR != 3)
			DIR = 1;
		break;
	case 77:
	case 'D':
	case 'd':
		if (DIR != 4)
			DIR = 2;
		break;
	case 80:
	case 'S':
	case 's':
		if (DIR != 1)
			DIR = 3;
		break;
	case 75:
	case 'A':
	case 'a':
		if (DIR != 2)
			DIR = 4;
		break;
	default:
		break;
	}
}

void movesnake(Snake& S)
{//控制蛇的移动
	for (int i = S.length - 1; i > 0; i--)
	{
		S.coor[i].first = S.coor[i - 1].first;
		S.coor[i].second = S.coor[i - 1].second;
	}
	switch (S.dir)
	{
	case 1:
		S.coor[0].second -= 10;
		break;
	case 2:
		S.coor[0].first += 10;
		break;
	case 3:
		S.coor[0].second += 10;
		break;
	case 4:
		S.coor[0].first -= 10;
		break;
	default:
		break;
	}

}

int isdead(Snake S)
{//检测蛇是否死亡
	if (S.coor[0].first > 640 - R || S.coor[0].first < R || S.coor[0].second>480 - R || S.coor[0].second <= R)
		return 1;
	else
	{
		for (int i = 4; i < S.length; i++)
		{
			if (S.coor[0].first >= S.coor[i].first - R && S.coor[0].first <= S.coor[i].first + R
				&& S.coor[0].second >= S.coor[i].second - R && S.coor[0].second <= S.coor[i].second + R)
				return 1;
		}
		return 0;
	}
}

void Eating(Snake& S, food& F)
{//蛇与食物的交互
	if (S.coor[0].first >= F.place[F.score].first - R && S.coor[0].first <= F.place[F.score].first + R
		&& S.coor[0].second >= F.place[F.score].second - R && S.coor[0].second <= F.place[F.score].second + R)
	{
		F.score++;
		S.length++;
	}
}

void drawsnake(Snake& S, food F)
{//画蛇
	char out[3] = {};

	BeginBatchDraw();
	while (1)
	{
		cleardevice();
		for (int i = 0; i < S.length; i++)
		{
			int x = S.coor[i].first;
			int y = S.coor[i].second;
			if (i == 0)
			{
				setfillcolor(GREEN);
				solidrectangle(x - R, y - R, x + R, y + R);
			}

			else
			{
				setcolor(WHITE);
				rectangle(x - R, y - R, x + R, y + R);
			}

		}
		int m = F.place[F.score].first;
		int n = F.place[F.score].second;
		setfillcolor(WHITE);
		solidrectangle(m - R, n - R, m + R, n + R);

		sprintf_s(out, "%d", F.score * S.speed);
		setbkmode(0);
		outtextxy(570, 20, "得分");
		outtextxy(620, 20, out);

		FlushBatchDraw();
		Sleep(200 - S.speed * 30);

		while (_kbhit())
		{
			control_dir(S.dir);
		}

		movesnake(S);

		Eating(S, F);
		if (isdead(S))
			break;
	}
	cleardevice();
	sprintf_s(out, "%d", F.score * S.speed);
	outtextxy(280, 180, "得分");
	outtextxy(320, 180, out);
	outtextxy(280, 200, "按Enter键继续");

	FlushBatchDraw();
	getchar();
	EndBatchDraw();
}

void menu()
{//菜单
	initgraph(640, 480);
	int flag = 1;
	while (flag)
	{
		cleardevice();
		outtextxy(280, 180, "贪吃蛇小游戏");
		outtextxy(280, 200, "1.开始游戏");
		outtextxy(280, 220, "2.结束游戏");
		char ch = _getch();
		switch (ch)
		{
		case '1':
		{
			food F;
			Initfood(F);

			Snake S;
			hatch(S);
			control_speed(S.speed);
			drawsnake(S, F);
			break;
		}
		case '2':
			flag = 0;
			break;
		default:
			break;
		}
	}
	closegraph();
}

int main(void)
{
	menu();
	return 0;
}
